Screens & Widgets topic
Screens & Widgets
The presentation layer is organized by feature area under lib/presentation/screens/. Navigation uses GoRouter with shell routes for persistent chrome.
Routing
The route table is declared in lib/config/routes.dart. Key patterns:
- Named routes for every destination (
/,/domains,/tutor,/review,/lesson/:id,/org,/settings/:section, …). - Auth guards via a
redirectthat inspectsauthStateProvider— unauthenticated users hit/auth/login, authenticated but onboarding-incomplete users hit/onboarding/<step>. - Shell routes wrap the post-auth tree in
OrgShellScaffold, which owns the bottom nav / side rail and the AppBar. Routes that live outside the shell (auth, onboarding, lesson full-screen) declare themselves at the top level. - Deep links route into the same tree via
Uriparsing — push notifications and OAuth redirects land directly on the right screen.
Screen categories
presentation/screens/
├── admin_onboarding/ Org admin 4-step setup wizard
├── auth/ Login, signup, MFA, password reset
├── backoffice/ Platform-admin-only views
├── domains/ Curriculum domain list + detail
├── goals/ Learning goals
├── home/ Landing screen with recent activity
├── lesson/ The core learning loop (Socratic + quiz + review)
├── notes/ User notes
├── onboarding/ 5-step first-connection flow
├── org/ Organization admin screens
├── progress/ Progress dashboards (mastery, XP, streaks)
├── review/ Spaced-repetition review queue
├── settings/ User + org settings
├── setup/ BYO Supabase bootstrap (Management API)
└── tutor/ Free-form Socratic dialogue
Responsive layout
OrgShellScaffold swaps navigation primitives based on viewport width:
- < 800 px — bottom
NavigationBar(mobile / narrow web). - ≥ 800 px — side
NavigationRail(tablet / desktop / wide web).
The viewport threshold is exported as a constant so pages can mirror it for their own responsive choices.
Key reusable widgets
| Widget | Purpose |
|---|---|
web_content_frame.dart |
Centers + max-widths content on web so the app doesn't stretch across 4K screens. The most-imported widget in the codebase. |
role_gate.dart |
Conditional render based on entitlement lookups. RoleGate(roles: [Role.admin], child: …). |
notification_bell.dart |
AppBar bell icon with unread badge. Watches notificationProvider. |
app_mode_toggle.dart |
Switch between learner and admin modes (the AppBar control shown in org mode). |
Testing patterns
Widget tests live in test/presentation/ and use alchemist for golden-file comparisons (tagged golden). Integration tests (test/integration/, tagged integration) run against a local Supabase and exercise the full stack — see test/integration/ for the datasource-level test suite pattern.
Classes
- OrgDetailScaffold
-
Shared scaffold for
/org/:orgId/<sub>detail screens that aren't part of the five shell destinations (Dashboard, Members, Assignments, Analytics, Settings). Renders an AppBar with the platform back button and, on narrow viewports, the same bottom NavigationBar as OrgShellScaffold so the user can escape to any of the main destinations in one tap. - OrgShellScaffold
-
Responsive shell for admin/manager org mode. Mirrors the personal
ScaffoldWithNavBarlayout but routes to /org/:orgId/* destinations. - RoleGate
- Conditionally renders child based on the current user's org role.
- WebContentFrame
- Constrains content width on desktop while passing through on mobile.